﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using System.Data.Odbc;
using System.Reflection;
using System.Web;

namespace WLMCoreLibrary
{
    public class WLMClassBinder
    {
        
        private dbConnector ConexionDB;

        public WLMClassBinder(ref dbConnector dbConn)
        {
            ConexionDB = dbConn;
        }
        public bool GetRecord(object classObject, string queryString)
        {
            OdbcDataReader reader = ConexionDB.ExecuteReader(queryString);
            int x = 0;
            Type objectType = classObject.GetType();
            FieldInfo[] members = objectType.GetFields(BindingFlags.NonPublic | BindingFlags.Instance);

            if (reader.HasRows)
            {
                for (x = 0; x < reader.FieldCount; x++)
                {
                    if (!reader.IsDBNull(x))
                    {
                        FieldInfo field = objectType.GetField("_" + reader.GetName(x), BindingFlags.NonPublic | BindingFlags.Instance);

                        Type tipo = field.FieldType;
                        if (reader[field.Name.ToString().Substring(1)] != null)
                        {
                            switch (reader.GetFieldType(x).ToString())
                            {
                                case "System.Int32":
                                    field.SetValue(classObject, (System.Int32)reader[x]);
                                    break;
                                case "System.DateTime":
                                    field.SetValue(classObject, Convert.ToDateTime(reader[x]));
                                    break;
                                case "System.Decimal":
                                    field.SetValue(classObject, (System.Decimal)reader[x]);
                                    break;
                                case "System.String":
                                    field.SetValue(classObject, (System.String)reader[x]);
                                    break;
                                case "System.Int16":
                                    field.SetValue(classObject, Convert.ToBoolean(reader[x]));
                                    break;
                                case "System.Boolean":
                                    //field.SetValue(classObject, Convert.ToBoolean(reader[field.Name.ToString().Substring(1)].ToString()));
                                    break;
                            }
                        }
                    }


                }
                classObject = null;
                reader.Close();
                reader.Dispose();
                return true;
            }
            else
            {
                //FieldInfo field = objectType.GetField("_isNull", BindingFlags.NonPublic | BindingFlags.Instance);
                //field.SetValue(classObject, true);
                reader.Dispose();
                return false;
            }


        }

        public string GetRecord1(string queryString)
        {
            string salidaGet = "private void GetRecord(string queryString)\r\n";
            OdbcDataReader reader = ConexionDB.ExecuteReader(queryString);
            salidaGet += "{\r\nOdbcDataReader reader = ConexionDB.ExecuteReader(queryString);\r\n";
            int x = 0;

            salidaGet += "if (reader.HasRows)\r\n{\r\n";

            if (reader.HasRows)
            {
                for (x = 0; x < reader.FieldCount; x++)
                {
                    salidaGet += "if(!reader.IsDBNull(reader.GetOrdinal(\"" + reader.GetName(x) + "\")))\r\n";

                    switch (reader.GetFieldType(x).ToString())
                    {
                        case "System.Int32":

                            salidaGet += "" + reader.GetName(x) + "=(System.Int32)reader[\"" + reader.GetName(x) + "\"];\r\n";
                            break;
                        case "System.DateTime":
                            //field.SetValue(classObject, Convert.ToDateTime(reader[x]));
                            salidaGet += "" + reader.GetName(x) + "=Convert.ToDateTime(reader[\"" + reader.GetName(x) + "\"]);\r\n";
                            break;
                        case "System.Decimal":
                            //field.SetValue(classObject, (System.Decimal)reader[x]);
                            salidaGet += "" + reader.GetName(x) + "=(System.Decimal)reader[\"" + reader.GetName(x) + "\"];\r\n";
                            break;
                        case "System.String":
                            //field.SetValue(classObject, (System.String)reader[x]);
                            salidaGet += "" + reader.GetName(x) + "=(System.String)reader[\"" + reader.GetName(x) + "\"];\r\n";
                            break;
                        case "System.Int16":

                            //field.SetValue(classObject, Convert.ToBoolean(reader[x]));
                            salidaGet += "" + reader.GetName(x) + "=Convert.ToBoolean(reader[\"" + reader.GetName(x) + "\"]);\r\n";
                            break;
                        case "System.Boolean":
                            //field.SetValue(classObject, Convert.ToBoolean(reader[field.Name.ToString().Substring(1)].ToString()));
                            break;
                    }



                }
                //classObject = null;
                reader.Close();
                reader.Dispose();
                salidaGet += "}\r\n}\r\n";
                return salidaGet;


            }
            return null;

        }

        public string GetRecordDataRow(string queryString)
        {
            string salidaGet = "\r\n\r\nprivate void GetRecord(DataRow dataRow)\r\n";
            OdbcDataReader reader = ConexionDB.ExecuteReader(queryString);
            salidaGet += "{\r\n";
            int x = 0;

            salidaGet += "if (dataRow!=null)\r\n{\r\n";

            if (reader.HasRows)
            {
                for (x = 0; x < reader.FieldCount; x++)
                {
                    salidaGet += "if(dataRow[\"" + reader.GetName(x) + "\"]!=null)\r\n";

                    switch (reader.GetFieldType(x).ToString())
                    {
                        case "System.Int32":

                            salidaGet += "\t" + reader.GetName(x) + "=(System.Int32)dataRow[\"" + reader.GetName(x) + "\"];\r\n";
                            break;
                        case "System.DateTime":
                            //field.SetValue(classObject, Convert.ToDateTime(reader[x]));
                            salidaGet += "" + reader.GetName(x) + "=(System.DateTime)dataRow[\"" + reader.GetName(x) + "\"];\r\n";
                            break;
                        case "System.Decimal":
                            //field.SetValue(classObject, (System.Decimal)reader[x]);
                            salidaGet += "" + reader.GetName(x) + "=(System.Decimal)dataRow[\"" + reader.GetName(x) + "\"];\r\n";
                            break;
                        case "System.String":
                            //field.SetValue(classObject, (System.String)reader[x]);
                            salidaGet += "" + reader.GetName(x) + "=(System.String)dataRow[\"" + reader.GetName(x) + "\"];\r\n";
                            break;
                        case "System.Int16":

                            //field.SetValue(classObject, Convert.ToBoolean(reader[x]));
                            salidaGet += "" + reader.GetName(x) + "=()(bool)dataRow[\"" + reader.GetName(x) + "\"];\r\n";
                            break;
                        case "System.Boolean":
                            //field.SetValue(classObject, Convert.ToBoolean(reader[field.Name.ToString().Substring(1)].ToString()));
                            break;
                    }



                }
                //classObject = null;
                reader.Close();
                reader.Dispose();
                salidaGet += "}\r\n}\r\n";
                return salidaGet;


            }
            return null;

        }
        //public int NewRecord(string tableName)
        //{
        //    int id;
        //    try
        //    {
        //        string queryString = "";
        //        DateTime fechaCreacion = DateTime.UtcNow.AddHours(-6);
        //        int idUsuario =CurrentOpenId.IdUsuario;
        //        queryString = "Insert into " + tableName + " (fechaCreacion,fechaModificacion,idUsuario) values ('" + fechaCreacion.ToString("yyyy-MM-dd HH:mm:ss") + "','" + fechaCreacion.ToString("yyyy-MM-dd HH:mm:ss") + "','"+ idUsuario.ToString()+"')";
        //        ConexionDB.ExecuteCommand(queryString);

        //        queryString = "SELECT id FROM " + tableName + " WHERE fechaCreacion='" + fechaCreacion.ToString("yyyy-MM-dd HH:mm:ss") + "' AND fechaModificacion='" + fechaCreacion.ToString("yyyy-MM-dd HH:mm:ss") + "' AND idUsuario='" + idUsuario.ToString() + "' limit 1";
        //        OdbcDataReader reader = ConexionDB.ExecuteReader(queryString);
        //        if (reader.HasRows)
        //            id = Convert.ToInt32(reader["id"]);
        //        else
        //            id = 1;
        //        reader.Close();

        //        return id;
        //    }
        //    catch
        //    {
        //        return 0;
        //    }
        //}

        public int NewRecord(string tableName)
        {
            int id;
            try
            {
                StringBuilder queryString = new StringBuilder();
OdbcDataReader reader;
                if(ConexionDB.DBType==2)
                     reader= ConexionDB.ExecuteReader("SELECT TOP 1 id FROM " + tableName + " ORDER BY id DESC");
                else
                    reader= ConexionDB.ExecuteReader("SELECT id FROM " + tableName + " ORDER BY id DESC limit 1");
                if (reader.HasRows)
                    id = Convert.ToInt32(reader["id"]) + 1;
                else
                    id = 1;
                reader.Close();
                //LogedUserData currentUser = new LogedUserData();

                queryString.Append("Insert into " + tableName+" (");
                if (ConexionDB.DBType != 2)
                    queryString.Append("id,");
                queryString.Append("fechaCreacion,fechaModificacion,idUsuario) values (");
                if (ConexionDB.DBType != 2)
                    queryString.Append(id + ",");
                queryString.Append("'"+DateTime.UtcNow.AddHours(-6).ToString("yyyy-MM-dd HH:mm:ss") + "','");
                queryString.Append(DateTime.UtcNow.AddHours(-6).ToString("yyyy-MM-dd HH:mm:ss") + "','");
                try
                {
                    queryString.Append(CurrentUser.IdUsuario + "')");
                }
                catch
                {
                    queryString.Append(1 + "')");
                }


                ConexionDB.ExecuteCommand(queryString.ToString());
                return id;
            }
            catch (Exception ex)
            {
                HttpContext.Current.Response.Write(ex.Message+ex.StackTrace);
                //HttpContext.Current.Response.End();
                return 0;
            }
        }

        public Guid NewGUID(string tableName)
        {
            Guid guid;
            try
            {
                StringBuilder queryString = new StringBuilder();
                //OdbcDataReader reader;
                //if (ConexionDB.DBType == 2)
                //    reader = ConexionDB.ExecuteReader("SELECT TOP 1 id FROM " + tableName + " ORDER BY id DESC");
                //else
                //    reader = ConexionDB.ExecuteReader("SELECT id FROM " + tableName + " ORDER BY id DESC limit 1");
                //if (reader.HasRows)
                //    id = Convert.ToInt32(reader["id"]) + 1;
                //else
                //    id = 1;
                //reader.Close();
                //LogedUserData currentUser = new LogedUserData();
                guid = Guid.NewGuid();
                queryString.Append("Insert into " + tableName + " (");
                if (ConexionDB.DBType != 2)
                    queryString.Append("GUID,");
                queryString.Append("fechaCreacion,fechaModificacion,idUsuario) values (");
                if (ConexionDB.DBType != 2)
                    queryString.Append("'"+guid.ToString() + "',");
                queryString.Append("'" + DateTime.UtcNow.AddHours(-6).ToString("yyyy-MM-dd HH:mm:ss") + "','");
                queryString.Append(DateTime.UtcNow.AddHours(-6).ToString("yyyy-MM-dd HH:mm:ss") + "','");
                try
                {
                    queryString.Append(CurrentUser.IdUsuario + "')");
                }
                catch
                {
                    queryString.Append(1 + "')");
                }


                ConexionDB.ExecuteCommand(queryString.ToString());
                return guid;
            }
            catch (Exception ex)
            {
                HttpContext.Current.Response.Write(ex.Message + ex.StackTrace);
                //HttpContext.Current.Response.End();
                return Guid.Empty;
            }
        }

        public void UpdateBind(string tableName, object classObject, int recordId)
        {

            string queryString = "";
            queryString = "SELECT * FROM " + tableName + " Limit 1";
            OdbcDataReader reader = ConexionDB.ExecuteReader(queryString);
            Type objectType = classObject.GetType();
            FieldInfo[] classfields = objectType.GetFields(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.FlattenHierarchy);

            FieldInfo lastModifiedField = objectType.GetField("_fechaModificacion", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.FlattenHierarchy);
            lastModifiedField.SetValue(classObject, DateTime.Now);
            queryString = "UPDATE " + tableName + " set ";
            int y = 0;
            int limite = reader.FieldCount;
            bool inicio = false;
            reader.Read();

            for (y = 0; y < reader.FieldCount; y++)
            {
                if (reader.GetName(y) != "id")
                {
                    FieldInfo field = objectType.GetField("_" + reader.GetName(y), BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.FlattenHierarchy);
                    if (field != null)
                    {
                        if (inicio)
                        {
                            queryString += ",";
                        }
                        inicio = true;
                        if (field.FieldType.ToString() == "System.Boolean")
                            queryString += field.Name.ToString().Substring(1) + "='" + Convert.ToInt16(field.GetValue(classObject)) + "'";
                        else
                        {
                            if (field.FieldType.ToString() == "System.DateTime")
                            {
                                DateTime fecha = Convert.ToDateTime(field.GetValue(classObject));

                                queryString += field.Name.ToString().Substring(1) + "='" + fecha.ToString("yyyy-MM-dd HH:mm:ss") + "'";

                            }
                            else
                                queryString += field.Name.ToString().Substring(1) + "='" + field.GetValue(classObject) + "'";
                        }
                    }
                }

            }
            queryString += " WHERE id='" + recordId + "'";
            reader.Close();
            ConexionDB.ExecuteCommand(queryString);
        }

        public string UpdateBind1(string tableName)
        {
            string salida = "protected override void UpdateBind()\r\n{\r\n";
            string queryString = "";
            queryString = "SELECT * FROM " + tableName + " ";
            OdbcDataReader reader = ConexionDB.ExecuteReader(queryString);

            queryString = "UPDATE " + tableName + " set ";
            salida += "StringBuilder strCommand=new StringBuilder();\r\nstrCommand.Append(\"UPDATE " + tableName + " set \");\r\n";
            int y = 0;
            int limite = reader.FieldCount;
            bool inicio = false;
            reader.Read();


            for (y = 0; y < reader.FieldCount; y++)
            {
                if (reader.GetName(y) != "id" && reader.GetName(y) != "fechaCreacion" && reader.GetName(y) != "idUsuario")
                {

                    string comma = "";
                    if (inicio)
                    {
                        comma = ",";
                    }

                    inicio = true;
                    if (reader.GetFieldType(y).ToString() == "System.Int16")
                        salida += "strCommand.Append(\"" + comma + reader.GetName(y) + "='" + "\"+Convert.ToInt16(" + reader.GetName(y) + ")+\"'\"); \r\n";
                    else
                    {
                        if (reader.GetFieldType(y).ToString() == "System.DateTime")
                        {
                            if (reader.GetName(y) == "fechaModificacion")
                                salida += "strCommand.Append(\"" + comma + reader.GetName(y) + "='\"+DateTime.Now.ToString(\"yyyy-MM-dd HH:mm:ss\")+\"'\"); \r\n";
                            else
                                salida += "strCommand.Append(\"" + comma + reader.GetName(y) + "='\"+" + reader.GetName(y) + ".ToString(\"yyyy-MM-dd HH:mm:ss\")+\"'\"); \r\n";


                        }
                        else
                            if (reader.GetFieldType(y).ToString() == "System.Int32")
                                salida += "strCommand.Append(\"" + comma + reader.GetName(y) + "='\"+" + reader.GetName(y) + ".ToString()+\"'\");\r\n";
                            else
                                salida += "strCommand.Append(\"" + comma + reader.GetName(y) + "=\\\"\"+ WLMFunctions.comillas(" + reader.GetName(y) + ")+\"\\\"\");\r\n";
                    }

                }

            }
            salida += "strCommand.Append(\" WHERE id='\"+id+\"'\");\r\nConexionDBInterna.ExecuteCommand(strCommand.ToString());\r\n}\r\n ";
            //queryString += " WHERE id='" + recordId + "'";
            //reader.Close();
            //ConexionDB.ExecuteCommand(queryString);
            return salida;
        }

        public string[] ClassBuilder(string tableName, string objectName, string ClassName)
        {
            string strQuery = "SELECT * from " + tableName;
            string[] salidas = new string[4];
            OdbcDataReader lector = ConexionDB.ExecuteReader(strQuery);
            int x = 0;
            string clasOut = "";
            string strBulid = "", strColl = "", strProperties = "", strForm = "", strFormFill = "", strObjectFill = "";
            lector.Read();
            for (x = 0; x < lector.FieldCount; x++)
            {
                if (lector.GetName(x).ToString() != "id" && lector.GetName(x).ToString() != "fechaCreacion" && lector.GetName(x).ToString() != "fechaModificacion" && lector.GetName(x).ToString() != "idUsuario" && lector.GetName(x).ToString() != "idUsuarioModificacion")
                {
                    string fieldType = "";
                    switch (lector.GetFieldType(x).ToString())
                    {
                        case "System.Int32":
                            fieldType = "int";
                            break;
                        case "System.DateTime":
                            fieldType = "DateTime";
                            break;
                        case "System.Decimal":
                            fieldType = "Decimal";
                            break;
                        case "System.String":
                            fieldType = "String";
                            break;
                        case "System.Int16":
                            fieldType = "Boolean";
                            break;
                        case "System.Boolean":
                            //field.SetValue(classObject, Convert.ToBoolean(reader[field.Name.ToString().Substring(1)].ToString()));
                            break;
                    }

                    //strBulid += "private " + fieldType + " _" + lector.GetName(x).ToString() + ";\r\n";

                    strProperties += "public " + fieldType + " " + lector.GetName(x).ToString() + "{get; set;}\r\n";
                    if (fieldType == "Boolean")
                        strForm += "<br /><asp:CheckBox ID='" + lector.GetName(x).ToString() + "' runat='server' Text='" + lector.GetName(x).ToString() + "'/>\r\n";
                    else
                        strForm += "<br />" + lector.GetName(x).ToString() + ":<br/>\r\n<asp:TextBox ID='" + lector.GetName(x).ToString() + "' runat='server' Width='250px'></asp:TextBox>\r\n";

                    if (fieldType == "Boolean")
                        strFormFill += lector.GetName(x).ToString() + ".Checked=" + objectName + "." + lector.GetName(x).ToString() + ";\r\n";
                    else
                        strFormFill += lector.GetName(x).ToString() + ".Text=" + objectName + "." + lector.GetName(x).ToString() + ";\r\n";

                    if (fieldType == "Boolean")
                        strObjectFill += objectName + "." + lector.GetName(x).ToString() + "=" + lector.GetName(x).ToString() + ".Checked;\r\n";
                    else
                        strObjectFill += objectName + "." + lector.GetName(x).ToString() + "=" + lector.GetName(x).ToString() + ".Text;\r\n";

                }
                //public decimal subTotal { get { return _subTotal; } set { _subTotal = value; } }
            }
            lector.Close();
            clasOut += "public class " + ClassName + ":BaseClass\r\n"+
                "{\r\n" +
                "#region private fields\r\n" +
                "" + strBulid + "#endregion\r\n\r\n" +
                "#region public properties\r\n" +
                "" + strProperties + "" +
                "#endregion\r\n\r\n";
            strColl += "public class " + ClassName + "Collection\r\n" +
                "{\r\n" +
                "private dbConnector ConexionDB;\r\n " +
                "private BaseClassArray<" + ClassName + "> _items;\r\n " +
                "public BaseClassArray<" + ClassName + "> Elementos { get { return _items; } }\r\n " +
                "public " + ClassName + "Collection()\r\n " +
                "{\r\n  }\r\n      " +
                "public " + ClassName + "Collection(ref dbConnector dbConn)\r\n " +
                "{\r\n  \r\n          " +
                "string strCommand = \"SELECT id FROM " + tableName + " \";\r\n  " +
                "OdbcDataReader dataReader = ConexionDB.ExecuteReader(strCommand);\r\n        " +
                "_items = new BaseClassArray<" + ClassName + ">(); \r\n   " +
                "while (dataReader.Read())\r\n            " +
                "{\r\n  "+
                ClassName + " newItem = new " + ClassName + "(Convert.ToInt32(dataReader[\"id\"]),ref ConexionDB);\r\n" +
                "_items.Add(newItem);\r\n" +
                "}\r\ndataReader.Close();\r\n  dataReader.Dispose();\r\n}\r\n}";
            clasOut += "#region constructors\r\npublic " + ClassName + "(ref dbConnector dbConn)\r\n{\r\n\r\nWLMClassBinder classBinder = new WLMClassBinder(ref ConexionDB);\r\nid = classBinder.NewRecord(\"" + tableName + "\");\r\nstring queryString = \"\";\r\n"+
                "queryString = \"SELECT * FROM " + tableName + " WHERE id='\" + id + \"'\";\r\nGetRecord(queryString);    \r\n   }\r\n\r\n"+
                "public " + ClassName + "(int registryId,dbConnector dbConn)\r\n" +
                "{\r\n" +
                "string queryString = \"\";\r\n" +
                "queryString = \"SELECT * FROM " + tableName + " WHERE id='\" + registryId + \"'\";\r\n" +
                "WLMClassBinder classBinder = new WLMClassBinder(ref ConexionDB);\r\n" +
                "this.GetRecord(queryString);\r\n   }\r\n" +
            //Constructor de clase usando un dataRow
                "public " + ClassName + " (DataRow dataRow,dbConnector dbConn)\r\n" +
                "{\r\n" +
                "this.GetRecord(dataRow);\r\n" +
                "}\r\n" +
                "#endregion\r\n\r\n " +
                "#region public methods\r\n" +
                "public void Delete()\r\n" +
                "{\r\n" +
                "string queryString = \"\";\r\n"+
                "queryString = \"DELETE FROM " + tableName + " WHERE id='\" + id + \"'\";\r\n" +
                "ConexionDB.ExecuteCommand(queryString);    \r\n" +
                "} \r\n" +
                "#endregion\r\n\r\n" +
                "#region Private Methods\r\n" +
                GetRecord1(strQuery) + GetRecordDataRow(strQuery) + "\r\n" +
                "\r\n" + UpdateBind1(tableName) + "#endregion\r\n}\r\n\r\n";
            salidas[0] = clasOut + "\r\n\r\n\r\n" + strColl;
            salidas[1] = strForm;
            salidas[2] = strFormFill;
            salidas[3] = strObjectFill;
            return salidas;  //"------------- Codigo de Clase-------------\r\n\r\n" + clasOut + "\r\n\r\n\r\n"+strColl+ "\r\n\r\n\r\n---------------- Codigo Formulario Web ---------------\r\n\r\n" + strForm + "\r\n\r\n----------------- Llenado de Formulario Web desde Objeto ------------\r\n\r\n" + strFormFill + "\r\n\r\n----------------- Llenado de Objeto dede Formulario ------------\r\n\r\n" + strObjectFill;
        }
    }
}
